LambdaイベントソースのSNSからCloudWatch Alarm名を取得してみた
こんにちは、坂巻です。
LambdaのイベントソースにSNS越しに複数のCloudWatch Alarmがあり、呼び出し元になったCloudWatch Alarm名をLambda側で取得する方法についてのエントリです。呼び出し元になったCloudWatch Alarmによって、Lambdaで処理を分岐させるような事を想定して、CloudWatch Alarm名を取得してみました。この説明では少々伝わりづらいと思いますので、構成図を記載します。
構成
LambdaでCloudWatch Alarm名を取得することを目的にしているため、CloudWatch Alarmでモニタリングするメトリクスは何でもよかったのですが、今回はStepFunctions(ステートマシン)の正常終了、異常終了ごとにCloudWatch Alarmを作成しました。また、CloudWatch Alarmから、直接Lambdaを起動することはできないのでSNSをかませています。
設定
Lambda関数
SNSイベントからCloudWatch Alarm名を取得する関数として「TestFunction」を作成しました。コードは以下となります。
import json def lambda_handler(event, context): # SNSイベントを取得 message_unicode = event['Records'][0]['Sns']['Message'] # 文字列から辞書型に変換 message_dist = json.loads(message_unicode) # CloudWatchAlarm名を取得 event_sorce_alarm_name = message_dist['AlarmName'] print(event_sorce_alarm_name)
シンプルなコードですが、SNSイベントからCloudWatch Alarm名を取得する際に、イベントの一部が文字列として扱われており型の問題で少々ハマりました。 型変換を行うために、上記コードのハイライト部分の対応が必要でした。詳細については以下をご確認ください。
また、SNSからLambdaに送信されるイベントの内容については、こちらを参考にしました。
SNS
SNSトピック「TestTopic」を作成しました。サブスクリプションはLambda関数「TestFunction」を呼び出すようになっています。
StepFunctions(ステートマシン)
入力イベントによって、正常終了、異常終了が分岐するステートマシン「TestStateMachin」を作成しました。
定義は以下となります。
{ "StartAt": "IsSucceed", "States": { "IsSucceed": { "Type": "Choice", "Choices": [{ "Variable": "$.success", "StringEquals":"True", "Next": "Succeed" }], "Default": "Fail" }, "Fail": { "Type": "Fail" }, "Succeed": { "Type": "Succeed" } } }
CloudWatch Alarm
CloudWatch Alarmは、正常終了用と異常終了用でそれぞれ作成します。
正常終了用
ステートマシン正常終了のメトリクスExecutionsSucceeded
の値で「TestTopic」へ通知するCloudWatch Alarm「ExecutionsSucceededAlarm」を作成しました。
異常終了用
ステートマシン正常終了のメトリクスExecutionsFailed
の値で「TestTopic」へ通知するCloudWatch Alarm「ExecutionsFailedAlarm」を作成しました。
動作確認
アラートを発生させるために、ステートマシン「TestStateMachin」を実行します。まずは、ステートマシンが正常終了するように、入力イベントを渡します。
想定どおりステートマシンが正常終了しました。
正常終了を検知して、CloudWatch Alarm「ExecutionsSucceededAlarm」の状態が警告となります。
この警告をトリガーに、Lambdaが実行されていますので、CloudWatch LogsよりCloudWatch Alarm名を確認してみます。
呼び出し元となったCloudWatch Alarm名「ExecutionsSucceededAlarm」の取得が確認できました。
次は、ステートマシンが異常終了するように、入力イベントを渡します。
想定どおりステートマシンが異常終了しました。
異常終了を検知して、CloudWatch Alarm「ExecutionsFailedAlarm」の状態が警告となります。
この警告をトリガーに、Lambdaが実行されていますので、CloudWatch LogsよりCloudWatch Alarm名を確認してみます。
呼び出し元となったCloudWatch Alarm名「ExecutionsFailedAlarm」の取得が確認できました。
さいごに
複数のCloudWatch Alarmから単一のLambdaを呼び出し、かつ、呼び出し元のCloudWatch AlarmによりLambdaで処理を分岐させるようなと時に使用できるかと思います。 どこかの誰かのお役に立てば嬉しいです。